package com.quanyan.comment.service.impl;


import com.google.common.base.Function;
import com.google.common.collect.ImmutableMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.lefu.commons.utils.Page;
import com.quanyan.api.APIResponse;
import com.quanyan.api.enums.ApiResponseEnum;
import com.quanyan.comment.constants.UserCenterConstants;
import com.quanyan.comment.mapper.*;
import com.quanyan.comment.model.po.*;
import com.quanyan.comment.reqeust.ReqBaseParam;
import com.quanyan.comment.reqeust.ReqCommentParam;
import com.quanyan.comment.reqeust.ReqCommentQuery;
import com.quanyan.comment.reqeust.ReqIsComment;
import com.quanyan.comment.response.*;
import com.quanyan.comment.service.*;
import com.quanyan.comment.utils.ValidUtils;
import com.quanyan.common.Plugin.PageObj;
import com.quanyan.common.constants.Constants;
import com.quanyan.user.response.RespUserInfoBase;
import com.quanyan.user.response.RespUserShowInfo;
import com.quanyan.user.serviceFacade.UserServiceFacade;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by jian.zhou on 2016/5/26.
 */
@Service
public class CommentServiceImpl implements CommentService {

    private static final Logger logger = LoggerFactory.getLogger(CommentServiceImpl.class);

    @Autowired
    private TbCommentMapper tbCommentMapper;

    @Autowired
    private CommentMapper commentMapper;

    @Autowired
    private TbCommentDetailScoreMapper tbCommentDetailScoreMapper;

    @Autowired
    private CommentSumService commentSumService;

    @Autowired
    private CommentPicMapper commentPicMapper;

    @Autowired
    private TbCommentPicMapper tbCommentPicMapper;

    @Autowired
    private CommentTagService commentTagService;

    @Autowired
    private CommentTagUserMapper commentTagUserMapper;

    @Autowired
    private CommentDetailService commentDetailService;


    @Autowired
    private TbCommentTagUserMapper tbCommentTagUserMapper;


    @Autowired
    private UserServiceFacade userServiceFacade;

    @Autowired
    private SensitiveService sensitiveService;


    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    public APIResponse commentAdd(ReqCommentParam reqCommentParam) {
        logger.info("comment insert  =====》 start {}", reqCommentParam.toString());
        //验证参数
        ValidUtils<ReqCommentParam> v = new ValidUtils<ReqCommentParam>();
        List<String> lstErrorMsg = v.getListMessage(reqCommentParam);
        if (lstErrorMsg != null && lstErrorMsg.size() > 0) {
            logger.info(lstErrorMsg.toString());
            return APIResponse.returnFail(lstErrorMsg, ApiResponseEnum.PARAMETER_CANT_BE_EMPTY);
        }

        if (reqCommentParam.getCommentType().equals(UserCenterConstants.CommentType.REPLAY)) {//评论类型为回复
            if (reqCommentParam.getToUserId() == null) {
                logger.info("comment insert  =====》 toUserId不能为空");
                return APIResponse.returnFail("toUserId不能为空", ApiResponseEnum.PARAMETER_CANT_BE_EMPTY);
            }

            if (reqCommentParam.getReplayId() == null) {
                logger.info("comment insert  =====》 replayId不能为空");
                return APIResponse.returnFail("replayId不能为空", ApiResponseEnum.PARAMETER_CANT_BE_EMPTY);
            }
        }

        try {
            TbComment tbComment = new TbComment();
            tbComment.setSystemCode(reqCommentParam.getSystemCode());
            tbComment.setBusinessCode(reqCommentParam.getBusinessCode());
            tbComment.setBusinessId(reqCommentParam.getBusinessId());
            tbComment.setCommentType(reqCommentParam.getCommentType().byteValue());
            tbComment.setCommentStatus(UserCenterConstants.Status.ABLE.byteValue());
            tbComment.setCommentContent(reqCommentParam.getCommentContent());
            tbComment.setFromUser(reqCommentParam.getFromUserId());
            tbComment.setToUser(reqCommentParam.getToUserId());
            tbComment.setReplayId(reqCommentParam.getReplayId());
            tbComment.setCommonParam(reqCommentParam.getCommonParam());
            tbComment.setSubNo(reqCommentParam.getOrderNo());
            tbComment.setAnonymous(reqCommentParam.getAnonymous());
//            if (sensitiveService.isExistsKey(reqCommentParam.getCommentContent())){
//                tbComment.setCommentStatus(UserCenterConstants.Status.DISABLE.byteValue());
//            }

            if (reqCommentParam.getScore() == null || reqCommentParam.getScore() == 0) {
                //判断评价业务子项目是否存在
                if (reqCommentParam.getLstCommentDetailScore() != null && reqCommentParam.getLstCommentDetailScore().size() > 0) {
                    logger.info("comment insert  =====》 开始计算平均分------------》");
                    Double totalScore = 0.0;
                    for (Map<String, Object> r : reqCommentParam.getLstCommentDetailScore()) {
                        TbCommentDetailScore t = new TbCommentDetailScore();
                        Double tmp = (Double) r.get("score");
                        totalScore += tmp;
                    }
                    Double avg = totalScore / reqCommentParam.getLstCommentDetailScore().size();
                    logger.info("comment insert  =====》 总分{},平均分------------》{}", totalScore, avg);
                    tbComment.setScore(Math.floor(avg));
                } else {
                    tbComment.setScore(0.0);
                }
            } else {
                tbComment.setScore(reqCommentParam.getScore());
            }
            tbCommentMapper.insertSelective(tbComment);

            //增加图片评论
            if (reqCommentParam.getLstPic() != null && reqCommentParam.getLstPic().size() > 0) {
                logger.info("comment insert img =====》 开始插入图片评论");
                List<TbCommentPic> lstPic = new ArrayList<>();
                for (String pic : reqCommentParam.getLstPic()) {
                    TbCommentPic tbCommentPic = new TbCommentPic();
                    tbCommentPic.setCommentId(tbComment.getId());
                    tbCommentPic.setPicUrl(pic);
                    lstPic.add(tbCommentPic);
                }
                commentPicMapper.batchSave(lstPic);
                logger.info("comment insert img =====》 结束插入图片评论");
            }

            //判断评价业务子项目是否存在
            if (reqCommentParam.getLstCommentDetailScore() != null && reqCommentParam.getLstCommentDetailScore().size() > 0) {
                logger.info("comment insert comment pro =====》 业务子项");
                Integer num = reqCommentParam.getLstCommentDetailScore().size();
                List<TbCommentDetailScore> lst = new ArrayList<TbCommentDetailScore>();
                Double totalScore = 0.0; //

                for (Map<String, Object> r : reqCommentParam.getLstCommentDetailScore()) {
                    TbCommentDetailScore t = new TbCommentDetailScore();
                    t.setCommentId(tbComment.getId());
                    t.setCommentDetailId(r.get("commentDetailId").toString());
                    t.setScore((Double) r.get("score"));
                    totalScore += t.getScore();
                    lst.add(t);
                }
                tbCommentDetailScoreMapper.batchSave(lst);
            }

            //用户标签
            List<Integer> lstTagId = reqCommentParam.getLstTagId();
            if (lstTagId != null && lstTagId.size() > 0) {
                logger.info("comment insert comment tag =====》{}", lstTagId.toString());
                Map<Integer, TbCommentTag> mapTag = commentTagService.batchCommentTagById(lstTagId);
                List<TbCommentTagUser> tbCommentTagUserList = new ArrayList<>();

                List<TbCommentTagSum> tbCommentTagSumList = new ArrayList<>();
                for (Integer id : lstTagId) {
                    TbCommentTagSum tbCommentTagSum = new TbCommentTagSum(); //汇总信心

                    TbCommentTagUser tbCommentTagUser = new TbCommentTagUser();//明细
                    tbCommentTagUser.setTagId(id);
                    tbCommentTagUser.setCommentId(tbComment.getId());
                    tbCommentTagUser.setUid(reqCommentParam.getFromUserId());
                    if(mapTag.get(id) != null){
                        tbCommentTagUser.setTagName(mapTag.get(id).getTagName());
                        tbCommentTagSum.setTagName(mapTag.get(id).getTagName());
                    }
                    tbCommentTagUserList.add(tbCommentTagUser);

                    tbCommentTagSum.setSystemCode(reqCommentParam.getSystemCode());
                    tbCommentTagSum.setBusinessCode(reqCommentParam.getBusinessCode());
                    tbCommentTagSum.setBusinessId(reqCommentParam.getBusinessId());
                    tbCommentTagSum.setTagId(id);
                    tbCommentTagSumList.add(tbCommentTagSum);

                }

                commentTagUserMapper.batchSave(tbCommentTagUserList);
                commentTagUserMapper.batchUpdate(lstTagId);
                if (tbCommentTagSumList.size() > 0)
                    commentTagService.commentTagTotal(tbCommentTagSumList,lstTagId);
                logger.info("comment insert comment tag =====》 ending");
            }
            //统计评论信息
            logger.info("comment insert total start ======> ");
            ReqBaseParam reqBaseParam = new ReqBaseParam();
            reqBaseParam.setSystemCode(reqCommentParam.getSystemCode());
            reqBaseParam.setBusinessCode(reqCommentParam.getBusinessCode());
            reqBaseParam.setBusinessId(reqCommentParam.getBusinessId());
            reqBaseParam.setCommonParam(reqCommentParam.getCommonParam());//达人活动新加

            if (Constants.CLUB_SYSTEM_CODE.equals(reqCommentParam.getCommonParam())){
                //俱乐部旧数据
                if (reqCommentParam.getCommonParam() != null)
                    reqBaseParam.setBusinessId(reqCommentParam.getCommonParam());
                else
                    reqBaseParam.setBusinessId(reqCommentParam.getBusinessId());
            }
            int starScore;
            if (tbComment.getScore() == null) {
                starScore = 0;
            } else {
                starScore = tbComment.getScore().intValue();
            }
            commentSumService.addCommentSum(reqBaseParam, starScore, reqCommentParam.getCommentType());
            logger.info("comment insert ======> success");
            return APIResponse.returnSuccess();
        } catch (Exception e) {
            logger.error("评论异常：{}", e);
            throw e;
        }
    }

    @Override
    public APIResponse<PageObj<List<RespComment>>> commentQuery(ReqCommentQuery reqCommentQuery) {
        logger.info("comment query start === > ：{}", reqCommentQuery.toString());
        //验证参数
        ValidUtils<ReqCommentQuery> v = new ValidUtils<ReqCommentQuery>();
        List<String> lstErrorMsg = v.getListMessage(reqCommentQuery);
        if (lstErrorMsg != null && lstErrorMsg.size() > 0)
            return APIResponse.returnFail(lstErrorMsg.toString());

        //分页
        Page<RespComment> page = new Page<RespComment>();
        int pageIndex = reqCommentQuery.getPageNum() + 1;
        page.setCurrentPage(pageIndex);
        page.setShowCount(reqCommentQuery.getPageSize());
        Map<String, Object> mapParam = reqCommentQuery.toMap();
        try {
            if (reqCommentQuery.isFlagRelay()) // 只查询是类型是评论的 评论
                mapParam.put("type", 1);
            List<RespComment> lstCommentDetail = commentMapper.findAllComments(page, mapParam);
            List<Integer> lstCId = new ArrayList<>();
            lstCId.addAll(this.coverListByPropertyId(lstCommentDetail));
            if (reqCommentQuery.isFlagRelay() && lstCId.size() > 0) {
                logger.info("comment query replay  === >");
                TbCommentExample tbCommentExample = new TbCommentExample();
                TbCommentExample.Criteria criteriaTbComment = tbCommentExample.createCriteria();
                criteriaTbComment.andReplayIdIn(lstCId);
                List<TbComment> lstTbComment = tbCommentMapper.selectByExample(tbCommentExample);
                for (RespComment r : lstCommentDetail) {
                    for (TbComment tbComment : lstTbComment) {
                        if (tbComment.getReplayId().intValue() == r.getId().intValue()) {
                            RespComment respComment = new RespComment();
                            respComment.setId(r.getId());
                            respComment.setSystemCode(tbComment.getSystemCode());
                            respComment.setBusinessCode(tbComment.getBusinessCode());
                            respComment.setBusinessId(tbComment.getBusinessId());
                            respComment.setFromUser(tbComment.getFromUser());
                            respComment.setToUser(tbComment.getToUser());
                            respComment.setCommentContent(tbComment.getCommentContent());
                            respComment.setCommentType(Integer.parseInt(tbComment.getCommentType().toString()));
                            respComment.setReplayId(tbComment.getReplayId());
                            respComment.setCommentStatus(Integer.parseInt(tbComment.getCommentStatus().toString()));
                            respComment.setCreateTime(tbComment.getCreateTime());
                            respComment.setScore(tbComment.getScore());
                            respComment.setCommonParam(tbComment.getCommonParam());
                            respComment.setOrderNo(tbComment.getSubNo());
                            respComment.setAnonymous(tbComment.getAnonymous());
                            r.getLstReplayComment().add(respComment);
                        }
                    }
                }
            }

            if (lstCommentDetail != null && lstCommentDetail.size() > 0) {//查询图片//todo  加缓存
                logger.info("query img--");
                TbCommentPicExample tbCommentPicExampleExample = new TbCommentPicExample();
                TbCommentPicExample.Criteria criteria = tbCommentPicExampleExample.createCriteria();
                criteria.andCommentIdIn(lstCId);
                List<TbCommentPic> lst = tbCommentPicMapper.selectByExample(tbCommentPicExampleExample); //图片

                TbCommentTagUserExample tbCommentTagUserExample = new TbCommentTagUserExample();
                TbCommentTagUserExample.Criteria tbCommentTagUserExampleCriteria = tbCommentTagUserExample.createCriteria();
                tbCommentTagUserExampleCriteria.andCommentIdIn(lstCId);
                List<TbCommentTagUser> lstTag = tbCommentTagUserMapper.selectByExample(tbCommentTagUserExample);//标签

                List<Integer> lstUid = new ArrayList<>();
                lstUid.addAll(ImmutableSet.copyOf(this.getCommentUid(lstCommentDetail)).asList()); //评论uid

                Map<Integer,RespUserInfoBase> mapUserInfo = new HashMap<>();
                try {
                    mapUserInfo = userServiceFacade.batchQueryUserInfoToMap(lstUid);
                } catch (Exception e) {
                    logger.error("{}",e);
                }

                for (RespComment r : lstCommentDetail) {
                    for (TbCommentPic tbCommentPic : lst) {
                        if (r.getId().intValue() == tbCommentPic.getCommentId().intValue()) {
                            RespPicture respPicture = new RespPicture();
                            respPicture.setCid(tbCommentPic.getId());
                            respPicture.setPicUrl(tbCommentPic.getPicUrl());
                            r.getLstPic().add(respPicture);
                        }
                    }

                    for (TbCommentTagUser tbCommentTagUser : lstTag) {
                        if (r.getId().intValue() == tbCommentTagUser.getCommentId().intValue()) {
                            RespCommentTag respCommentTag = new RespCommentTag();
                            respCommentTag.setId(tbCommentTagUser.getTagId());
                            respCommentTag.setTagName(tbCommentTagUser.getTagName());
                            r.getCommentTagList().add(respCommentTag);
                        }
                    }

                    if (mapUserInfo.containsKey(r.getFromUser())){
                        RespUserInfoBase respUserInfoBase = mapUserInfo.get(r.getFromUser());
                        RespUserShowInfo respUserShowInfo = new RespUserShowInfo();
                        respUserShowInfo.setHead(respUserInfoBase.getIcon());
                        respUserShowInfo.setNickname(respUserInfoBase.getNickName());
                        respUserShowInfo.setUid(r.getFromUser());
                        r.setRespUserShowInfo(respUserShowInfo);
                    }
                }
            }


            if (pageIndex > page.getTotalPage()) {
                lstCommentDetail = new ArrayList<>();
            }
            PageObj<List<RespComment>> result = PageObj.create(page.getTotalResult(), page.getCurrentPage(), page.getShowCount(), lstCommentDetail);
            logger.info("comment query end === > ：{}", lstCommentDetail.toString());
            return APIResponse.returnSuccess(result);
        } catch (Exception e) {
            logger.error("获取评论：{}异常：{}", reqCommentQuery.toString(), e);
            return APIResponse.returnFail("系统异常！");
        }
    }


    public Map<String, Object> queryCommentTwo(ReqCommentQuery reqCommentQuery) {
        APIResponse<PageObj<List<RespComment>>> apiResponse = this.commentQuery(reqCommentQuery);
        PageObj<List<RespComment>> pageObj = apiResponse.getData();
        reqCommentQuery.setPeopleTotal(1);
        List<RespCommentTag> commentTags = commentTagService.commentTagSum(reqCommentQuery);
        Map<String, Object> map = new HashMap<>();
        map.put("pageObj", pageObj);
        map.put("commentTags", commentTags);
        return map;
    }

    @Override
    public APIResponse commentDel(Integer commentId) {
        logger.info("开始删除评论：{}", commentId);
        if (commentId == null)
            return APIResponse.returnFail("commentId不能为空！", ApiResponseEnum.PARAMETER_CANT_BE_EMPTY);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("id", commentId);
        map.put("status", UserCenterConstants.Status.DISABLE);
        try {

            TbComment tbComment = tbCommentMapper.selectByPrimaryKey(commentId);
            if (tbComment.getCommentStatus() == Constants.IS_DELETE_FALSE) {
                logger.info("该评论已经删除！");
                return APIResponse.returnSuccess();
            }
            TbComment tbCommentUpdate = new TbComment();
            tbCommentUpdate.setId(tbComment.getId());
            tbCommentUpdate.setCommentStatus(Constants.IS_DELETE_FALSE);//删除
            tbCommentMapper.updateByPrimaryKeySelective(tbCommentUpdate);
            tbCommentDetailScoreMapper.updateStatus(map);
            ReqCommentQuery reqCommentQuery = new ReqCommentQuery();
            reqCommentQuery.setSystemCode(tbComment.getSystemCode());
            reqCommentQuery.setBusinessCode(tbComment.getBusinessCode());
            reqCommentQuery.setBusinessId(tbComment.getBusinessId());
            commentSumService.updateCommentSum(reqCommentQuery);
            logger.info("end ...删除评论");
            return APIResponse.returnSuccess();
        } catch (Exception e) {
            logger.error("删除评论异常：{},{}", commentId, e);
            return APIResponse.returnFail("系统异常!");
        }
    }


    public APIResponse<Boolean> checkIsComment(ReqIsComment reqIsComment) {
        //验证参数
        ValidUtils<ReqIsComment> v = new ValidUtils<ReqIsComment>();
        List<String> lstErrorMsg = v.getListMessage(reqIsComment);
        if (lstErrorMsg.size() > 0)
            return APIResponse.returnFail(lstErrorMsg.toString());

        TbCommentExample tbCommentExample = new TbCommentExample();
        TbCommentExample.Criteria criteria = tbCommentExample.createCriteria();

        criteria.andSystemCodeEqualTo(reqIsComment.getSystemCode());
        criteria.andBusinessCodeEqualTo(reqIsComment.getBusinessCode());
        criteria.andBusinessIdEqualTo(reqIsComment.getBusinessId());
        criteria.andFromUserEqualTo(reqIsComment.getUid());
        criteria.andCommentStatusEqualTo(UserCenterConstants.Status.ABLE.byteValue());
        int count = tbCommentMapper.countByExample(tbCommentExample);
        boolean flag = count > 0 ? true : false;//     *  true 已评论 false 未评论
        return APIResponse.returnSuccess(flag);
    }

    public boolean checkIsCommentPlace(ReqIsComment reqIsComment) {
        TbCommentExample tbCommentExample = new TbCommentExample();
        TbCommentExample.Criteria criteria = tbCommentExample.createCriteria();

        criteria.andSystemCodeEqualTo(reqIsComment.getSystemCode());
        criteria.andBusinessCodeEqualTo(reqIsComment.getBusinessCode());
        criteria.andBusinessIdEqualTo(reqIsComment.getBusinessId());
        criteria.andSubNoEqualTo(reqIsComment.getOrderNo());
        criteria.andCommentStatusEqualTo(UserCenterConstants.Status.ABLE.byteValue());
        int count = tbCommentMapper.countByExample(tbCommentExample);
        boolean flag = count > 0 ? true : false;//     *  true 已评论 false 未评论
        return flag;
    }


    public boolean checkIsReplace(ReqIsComment reqIsComment) {
        TbCommentExample tbCommentExample = new TbCommentExample();
        TbCommentExample.Criteria criteria = tbCommentExample.createCriteria();
        criteria.andReplayIdEqualTo(reqIsComment.getReplaceId());
        criteria.andFromUserEqualTo(reqIsComment.getUid());
        criteria.andCommentStatusEqualTo(UserCenterConstants.Status.ABLE.byteValue());
        int count = tbCommentMapper.countByExample(tbCommentExample);
        boolean flag = count > 0 ? true : false;//     *  true 已回复 false 未回复
        return flag;
    }


    public RespCommentTagAndCommentDetail getCommentTagAndCommentDetail(ReqCommentQuery reqCommentQuery) {
        logger.info("getCommentTagAndCommentDetail start query  :{}", reqCommentQuery.toString());
        RespCommentTagAndCommentDetail respCommentTagAndCommentDetail = new RespCommentTagAndCommentDetail();
        APIResponse<List<RespCommentTag>> apiResponseTag = commentTagService.commentTagQuery(reqCommentQuery);
        if (apiResponseTag.isRet())
            respCommentTagAndCommentDetail.setLstTag(apiResponseTag.getData());

        APIResponse<List<RespCommentDetail>> apiResponseDetail = commentDetailService.getCommentDetailPro(reqCommentQuery.getBusinessCode(), reqCommentQuery.getBusinessId());
        if (apiResponseDetail.isRet())
            respCommentTagAndCommentDetail.setLstCommentDetail(apiResponseDetail.getData());

        logger.info("getCommentTagAndCommentDetail end query :{}", reqCommentQuery.toString());
        return respCommentTagAndCommentDetail;
    }


    public APIResponse delDynamicComment(ReqCommentQuery reqCommentQuery) {
        TbCommentExample tbCommentExample = new TbCommentExample();
        TbCommentExample.Criteria criteria = tbCommentExample.createCriteria();
        criteria.andSystemCodeEqualTo(reqCommentQuery.getSystemCode());
        criteria.andBusinessCodeEqualTo(reqCommentQuery.getBusinessCode());
        criteria.andBusinessIdEqualTo(reqCommentQuery.getBusinessId());
        TbComment record = new TbComment();
        record.setCommentStatus(Constants.IS_DELETE_FALSE);
        tbCommentMapper.updateByExampleSelective(record, tbCommentExample);

        commentSumService.updateCommentSum(reqCommentQuery);
        try {
            tbCommentMapper.deleteByExample(tbCommentExample);
            return APIResponse.returnSuccess();
        } catch (Exception e) {
            logger.error("", e);
            return APIResponse.returnFail("系统异常");
        }
    }


    //list 按属性生成一个新的 list
    public ImmutableMultiset<Integer> coverListByPropertyId(List<RespComment> lst) {
        return ImmutableMultiset.copyOf(Lists.transform(lst, new Function<RespComment, Integer>() {
                    @Override
                    public Integer apply(RespComment input) {
                        return input.getId();
                    }
                }
        ));
    }

    //list 按属性生成一个新的 list
    public ImmutableMultiset<Integer> getCommentUid(List<RespComment> lst) {
        return ImmutableMultiset.copyOf(Lists.transform(lst, new Function<RespComment, Integer>() {
                    @Override
                    public Integer apply(RespComment input) {
                        return input.getFromUser();
                    }
                }
        ));
    }


    Function<TbCommentDetailScore, Integer> functionCommentDetailId = new Function<TbCommentDetailScore, Integer>() {
        @Override
        public Integer apply(TbCommentDetailScore person) {
            return Integer.parseInt(person.getCommentDetailId());
        }
    };
}
